/*
	Copyright (C) 2010 Salil Bhagurkar

	This file is part of k3

	k3 is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	k3 is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with k3.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <shared.h>


static char *kifs[] = {
/*0*/"help",
/*1*/"ls",
/*2*/"cd",
/*3*/"new",
/*4*/"put",
/*5*/"print",
/*6*/"tree",
/*7*/"run",
/*8*/"rename",
/*9*/"copy",
/*10*/"save",
/*11*/"load",
/*12*/"delete",
/*13*/"mode"};

static char *kif_help[] = {
"help: Display this",
"ls: List the contents of the current node",
"cd <path>: Change the current node",
"new <name>: Make a new node in the fs",
"put <data>: Put data in the current node",
"print: Print details of the current node",
"tree: Display tree of nodes in recursion",
"run: Run shit",
"rename <as_name>: Rename the current node from name to as_name",
"copy <node> <reparent>: Copy node 'node' to the directory 'reparent' specified including all children",
"save: Save to disk",
"load: Load from disk",
"delete <name>: Delete a node recursively",
"mode <RW>: Set runtime mode of current node"};


static struct fs *kif_interpret_command(struct fs *fs, char *buf)
{
	char buf1[MAX_FS_NAME_LEN];
	u32 cnt;
	struct fs *ch, *ch1;
	int e = 0, main_error = 0;
	getstringparameter(buf, buf1, ' ', 0);
	if(!strcmp(buf1, kifs[0])) {
		//help
		printk("k3 kinterface help: All path parameters are taken relative to the current node\n");
		for(cnt = 0; cnt < (sizeof(kifs)/sizeof(kifs[0])); cnt++) {
			printk("%s\n", kif_help[cnt]);
		}
	} else if(!strcmp(buf1, kifs[1])) {
		//ls
		e = 0;
		ch = fs;
		printk("Listing %s\n", ch->name);
		e = fsiter_get_child(&ch);
		while(!e) {
			printk("%s\n", ch->name);
			e = fsiter_get_next(&ch);
		}
	} else if(!strcmp(buf1, kifs[2])) {
		//cd
		getstringparameter(buf, buf1, ' ', 1);
		main_error = fsiter_parse(&fs, buf1);
	} else if(!strcmp(buf1, kifs[3])) {
		//new
		getstringparameter(buf, buf1, ' ', 1);
		ch = fs_create(FSFLAGS_DATA, buf1);
		if(!ch) {
			main_error = EMEMERR;
		} else {
			main_error = fs_link(fs, ch);
		}
	} else if(!strcmp(buf1, kifs[4])) {
		//put
		getstringparameter(buf, buf1, ' ', 1); //The value/string
		char *strbuf;
		strbuf = buf + getstringparameter_offset(buf, ' ', 1);
		struct buffer *buf = buffer_from_string(strbuf);
		main_error = fs_write(NULL, fs, buf, 0, buf->len);
		buffer_free(buf);
	} else if(!strcmp(buf1, kifs[5])) {
		//print
		__fs_print(fs);
	} else if(!strcmp(buf1, kifs[6])) {
		//tree
		__fs_tree(fs);
	} else if(!strcmp(buf1, kifs[7])) {
		//fsrun
		getstringparameter(buf, buf1, ' ', 1);
		ch = fsparse_get_relative(fs, buf1);
		if(!ch) {
			main_error = ENOREG;
		} else
			fsrun(ch);
	} else if(!strcmp(buf1, kifs[8])) {
		//rename
		getstringparameter(buf, buf1, ' ', 1);
		main_error = fs_rename(NULL, fs, buf1);
	} else if(!strcmp(buf1, kifs[9])) {
		//copy
		getstringparameter(buf, buf1, ' ', 1);
		ch = fsparse_get_relative(fs, buf1); //get the source node
		getstringparameter(buf, buf1, ' ', 2);
		ch1 = fsparse_get_relative(fs, buf1); //get the reparent
		if(!ch || !ch1) {
			main_error = ENOREG;
		} else {
			fs_copy_recurse(ch1, ch);
		}
	} else if(!strcmp(buf1, kifs[10])) {
		//main_error = fs_serialize(fsparse_get("/devices/class/store/block/hd0"), 0, fs);
	} else if(!strcmp(buf1, kifs[11])) {
		//main_error = fs_deserialize(fs, 0, fsparse_get("/devices/class/store/block/hd0"));
	} else if(!strcmp(buf1, kifs[12])) {
		//delete
		getstringparameter(buf, buf1, ' ', 1);
		ch = fsparse_get_relative(fs, buf1);
		if(!ch) {
			main_error = ENOREG;
		} else {
			main_error = fs_unlink_recurse(ch);
		}
	} else if(!strcmp(buf1, kifs[13])) {
		//mode
		getstringparameter(buf, buf1, ' ', 1);
		u32 index, len = strlen(buf1);
		fs->flags &= ~FSFLAGS_MODE_MASK;
		if(buf1[0] == 'R') {
			fs->flags |= FSFLAGS_MODE_READ;
		} else if(buf1[0] == 'W') {
			fs->flags |= FSFLAGS_MODE_WRITE;
		}
	} else if(!strcmp(buf1, "xxx")) {
		__malloc_print_info(true, 0);
	} else {
		main_error = ENOREG;
		printk("Unknown command (%s)\n", buf1);
	}
	if(main_error) {
		printk("DONE(%s): ", buf);
		printerror(main_error);
		printk("\n");
	}
	return fs;
}



#define CMD(cmd) fs = kif_interpret_command(fs, cmd)


int kif_init(struct fs *this)
{
	int e;
	struct fs *fs;
	fsiter_parse(&fs, "/");

	CMD("new apps");
	CMD("cd apps");

	printk("Welcome to Platform for runtime configurable Applications\n");

	/*CMD("new edm");
	CMD("cd edm");
	
	//Accept a choice
	CMD("new choice");
	CMD("cd choice");
	CMD("copy /vmdrv/console/string .");
	CMD("cd string");
	CMD("mode R");
	
	//Display menu
	CMD("new menu");
	CMD("cd menu");
	CMD("put Employee Data Management System\n1. Add a new employee\n2. Remove an employee\n3. List employees\n>");
	CMD("copy /vmdrv/console/string .");
	CMD("cd string");
	CMD("mode W");
	CMD("cd ..");
	CMD("cd ..");
	
	CMD("cd ..");
	CMD("cd ..");*/
	
	
	CMD("new xmlTest");
	CMD("cd xmlTest");
	
	CMD("new testData");
	CMD("cd testData");
	CMD("mode W");
	CMD("put salil");
	CMD("cd ..");
	
	CMD("copy /devices/lib/xmlp .");
	CMD("cd xmlp");
	CMD("mode R");
	CMD("cd ..");

	

	struct buffer *buf = buffer_create(MAX_FS_NAME_LEN);

	while(1) {
		buffer_write_data(buf, "\0", 0, 1);
		printk("\n%s:kif>", fsparse_get_path(buf->data, fs));
		buf->len = 0;
		e = fs_read(NULL, fsparse_get("/vmdrv/console/string"), buf, 0, MAX_FS_NAME_LEN);
		buffer_write_data(buf, "\0", buf->len, 1);
		printk("\n");
		if(e) {
			printk("kif: Failed to read from input device\n");
			return e;
		}
		fs = kif_interpret_command(fs, (char *)buf->data);
	}
	return 0;
}
